package org.dtrevien.ihm;

import graphviz.api.GraphViz;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;

import org.dtrevien.Application;

public class MainFrame extends JFrame {

	protected JPanel mainContainer;
	
	protected JScrollPane leftScrollPane;
	protected JScrollPane rightScrollPane;
	
	protected JPanel viewL;
	protected JPanel viewR;
	protected JTextAreaLined textYUML;
	protected JTextAreaLined textDOT; 
	protected ImagePanel imagePanel;
	protected JButton refresh, saveAs, clear, undo, open;
	protected JSlider sizeSlider;
	protected JTextField folder;
	protected JFileChooser fchooser;
	
	protected final Application app;
	protected String yumlText, dotText;
	
	protected File out = new File("/tmp/out.png");

	protected MouseLsn mouseLsn;
	
	public MainFrame(Application app) {
		try {
		    for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
		        if ("Nimbus".equals(info.getName())) {
		            UIManager.setLookAndFeel(info.getClassName());
		            break;
		        }
		    }
		} catch (Exception e) {
		    // If Nimbus is not available, you can set the GUI to another look and feel.
		}
		
		this.app = app;
		try {
			this.yumlText = app.getFileContent(app.yuml);
			this.dotText = app.getFileContent(app.dot);
			
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		this.setTitle("yUML to Graphviz");
		setBounds(0, 0, 1400, 800);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		initAndShow();

		try {
			app.startApplication();
			regenImage();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void regenImage() throws IOException {
		GraphViz gv = new GraphViz();
		gv.add(this.dotText);
		gv.writeGraphToFile( gv.getGraph( gv.getDotSource(), "png" ), this.out );
		BufferedImage bim = ImageIO.read(this.out);
		this.imagePanel.setImage(bim);
		this.imagePanel.repaint();
	}

	private void regen() {
		try {
			this.app.restart(this.textYUML.getText());
			this.yumlText = this.app.getFileContent(this.app.yuml);
			this.dotText = this.app.getFileContent(this.app.dot);
			this.textDOT.setText(this.dotText);
			regenImage();
		} catch (IOException e1) {
			e1.printStackTrace();
		} catch (Exception e2) {
			e2.printStackTrace();
		}
	}
	
	private void initAndShow() {
		JPanel grid = new JPanel(new GridLayout(2, 1));
		JPanel buttongrid = new JPanel(new FlowLayout(FlowLayout.LEFT));
		JPanel top = new JPanel(new BorderLayout());
		JPanel topInner = new JPanel(new BorderLayout()), bottomInner = new JPanel(new BorderLayout());
		JPanel imagePanelButtons = new JPanel(new FlowLayout(FlowLayout.RIGHT,0,0));
		
		this.fchooser = new JFileChooser(this.app.getDesktop());
		FileFilter filter1 = new ExtensionFileFilter("YUML", new String[] { "yuml"});
		this.fchooser.setFileFilter(filter1);
		
		this.mouseLsn = new MouseLsn(this);
		
		this.mainContainer = new JPanel(new GridLayout(1,2));
		
		this.refresh = new JButton("Refresh");
		this.refresh.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				regen();
			}
		});
		
		this.saveAs = new JButton("Save as");
		this.saveAs.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					MainFrame.this.app.writeAllOnDesktop(MainFrame.this.folder.getText(), MainFrame.this.textYUML.getText());
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
		
		this.clear = new JButton("Clear");
		this.clear.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				MainFrame.this.textYUML.setText("");
			}
		});
		
		this.undo = new JButton("Undo");
		this.undo.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				MainFrame.this.textYUML.setText(MainFrame.this.yumlText);
			}
		});
		

		this.open = new JButton("Open...");
		this.open.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				int returnVal = MainFrame.this.fchooser.showOpenDialog(MainFrame.this);
				if (returnVal == JFileChooser.APPROVE_OPTION) {
					File f = MainFrame.this.fchooser.getSelectedFile();
					System.err.println("######## "+f.getAbsolutePath());
					if (MainFrame.this.app.getFileExtention(f).equals("yuml")) {
						try {
							MainFrame.this.textYUML.setText(MainFrame.this.app.getFileContent(f));
							MainFrame.this.app.restart(f);
							regen();
						} catch (Exception e1) {
							e1.printStackTrace();
						}
					}
				}
			}
		});
		
		this.folder = new JTextField(10);

		this.viewL = new JPanel();
		this.textYUML = new JTextAreaLined();
		//this.textYUML.setLineWrap(true);
		JPanel topYUML = new JPanel(new FlowLayout(FlowLayout.LEFT));
		topYUML.setPreferredSize(new Dimension(1, 30));
		topYUML.add(new JLabel(" yUML Code"));
		JScrollPane scrollYUML = new JScrollPane(this.textYUML);
		topInner.add(topYUML,BorderLayout.NORTH);
		topInner.add(scrollYUML, BorderLayout.CENTER);
		
		this.textDOT = new JTextAreaLined();
		//this.textDOT.setLineWrap(true);
		this.textDOT.setEditable(false);
		JScrollPane scrollDOT = new JScrollPane(this.textDOT);
		bottomInner.add(new JLabel(" DOT Code"),BorderLayout.NORTH);
		bottomInner.add(scrollDOT, BorderLayout.CENTER);
		
		this.viewL.setLayout(new BorderLayout());
		this.viewL.add(grid);
		grid.add(top);
		grid.add(bottomInner);
		buttongrid.add(this.refresh);
		buttongrid.add(new JLabel("         "));
		buttongrid.add(this.folder);
		buttongrid.add(this.saveAs);
		buttongrid.add(this.open);
		buttongrid.add(new JLabel("         "));
		buttongrid.add(this.clear);
		buttongrid.add(this.undo);
		top.add(topInner, BorderLayout.CENTER);
		top.add(buttongrid, BorderLayout.SOUTH);
		
		this.viewR = new JPanel(new BorderLayout());
		this.imagePanel = new ImagePanel();
		this.imagePanel.addMouseWheelListener(new MouseWheelListener() {
			
			@Override
			public void mouseWheelMoved(MouseWheelEvent e) {
				try {
					if (e.getWheelRotation() < 0 && MainFrame.this.imagePanel.getFactor() < 2) {
						MainFrame.this.imagePanel.setFactor(MainFrame.this.imagePanel.getFactor()+0.1f);
							MainFrame.this.imagePanel.redraw();
					}
					else if (e.getWheelRotation() > 0 && MainFrame.this.imagePanel.getFactor() > 0.5f) {
						MainFrame.this.imagePanel.setFactor(MainFrame.this.imagePanel.getFactor()-0.1f);
						MainFrame.this.imagePanel.redraw();
					}
					MainFrame.this.sizeSlider.setValue((int) (MainFrame.this.imagePanel.getFactor()*10));
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
		this.imagePanel.addMouseMotionListener(this.mouseLsn);
		this.imagePanel.addMouseListener(this.mouseLsn);

		this.sizeSlider = new JSlider(5, 20, 10);
		this.sizeSlider.addChangeListener(new ChangeListener() {
			
			@Override
			public void stateChanged(ChangeEvent e) {
				float f = ((JSlider)e.getSource()).getValue()/10.0f;
				MainFrame.this.imagePanel.setFactor(f);
				try {
					MainFrame.this.imagePanel.redraw();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
		
		imagePanelButtons.setPreferredSize(new Dimension(1, 30));
		imagePanelButtons.add(new JLabel("o "));
		imagePanelButtons.add(this.sizeSlider);
		imagePanelButtons.add(new JLabel(" O    "));
		this.viewR.add(this.imagePanel, BorderLayout.CENTER);
		this.viewR.add(imagePanelButtons, BorderLayout.NORTH);
		
		this.textYUML.addKeyListener(new KeyListener() {
			
			@Override
			public void keyTyped(KeyEvent arg0) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void keyReleased(KeyEvent arg0) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_S) regen();
			}
		});
		
		this.leftScrollPane = new JScrollPane(this.viewL);
		this.rightScrollPane = new JScrollPane(this.viewR);
		
		this.mainContainer.add(this.viewL);
		this.mainContainer.add(this.viewR);
		
		getContentPane().setLayout(new BorderLayout());
		getContentPane().add(this.mainContainer, BorderLayout.CENTER);
		
		setVisible(true);

		this.textYUML.setText(this.yumlText);
		this.textDOT.setText(this.dotText);
	}
	
}
